<style>
#docs-main li {
    margin: 1ex 0;
}

li code,
td code {
    white-space: nowrap;
    background: #fcfbfa;
    border: 1px solid #d0d5ec;
    padding: 0 3px;
}
li code {
    border-color: #efeeed;
}
.yui3-skin-sam table {
    width: auto;
}
.yui3-skin-sam td,
.yui3-skin-sam th {
    border: 0 none;
}

.demo    { width: 40%; }
.details { width: 60%; }
.before, .after { width: 47%; }
.after {
    margin-left: 5%;
}

#quickref code em {
    color: #900;
}
#quickref code strong {
    color: #090;
}
#quickref pre.code {
    margin-top: 0;
    margin-bottom: 0;
}

.spendy {
    color: #b00;
}
</style>
<div class="intro">
    <p>
        DataTable and supporting modules were rebuilt in version 3.5.0.  The
        new architecture is <strong>not fully backward compatible</strong> with
        versions 3.4.1 and prior.  This guide is to help answer questions that
        may come up when upgrading to the latest version.
    </p>

    <p>
        This guide focuses on 3.4.1 API compatibility.  It <strong>does not
        describe new features added in 3.5.0</strong> (there were a lot).
        Refer to the updated <a href="index.html">DataTable user guide</a> for
        that.
    </p>

    <p>
        If you are unable to upgrade due to unresolvable issues, you can use the
        <a href="../datatable-deprecated/index.html">`datatable-deprecated`</a>
        module suite, which is equivalent to the 3.4.1 implementation.  But be
        aware that these modules will be removed in a future version of YUI.
    </p>
</div>

<h2 id="overview">Overview of API changes from 3.4.1</h2>

<p>
    The architectural change resulted in the deprecation, replacement, or
    removal of nearly all attributes and properties from the version 3.4.1
    implementation.  Here is a quick list of the changes most likely to affect
    your upgrade:
</p>

<ol id="quickref">
    <li>
        <code>new <em>Y.DataTable.Base</em>(...)</code> &rarr;
        <code>new <strong>Y.DataTable</strong>({ ... })</code>
    </li>
    <li>
        <div class="yui3-g">
        <div class="yui3-u">
            ```
            new Y.DataTable.Base({
                columnset: [ ... ],
                recordset: [ ... ]
            });
            ```
        </div>
        <p class="yui3-u" style="line-height: 72px; margin: 0 1em;">&rarr;</p>
        <div class="yui3-u">
            ```
            new Y.DataTable({
                columns: [ ... ],
                data   : [ ... ]
            });
            ```
        </div>
        </div>
    </li>
    <li>
        (cells rendered as HTML by default) &rarr;
        <code>columns: [ { key: 'email', <strong>allowHTML: true</strong> }, ... ]</code>
    </li>
    <li>
        <code>table.plug(<em>Y.Plugin.DataTableSort</em>)</code> &rarr; <em>(plugin not needed)</em>
        <a href="#features">See below</a> or read
        <a href="index.html#sorting">the user guide</a>
    </li>
    <li>
        <code>table.plug(<em>Y.Plugin.DataTableScroll</em>, ...)</code> &rarr;
        <em>(plugin not needed)</em>
        <a href="#features">See below</a> or read
        <a href="index.html#scrolling">the user guide</a>
    </li>
    <li>
        <code>columnset: [ { <em>formatter: function (o) { ... }</em> } ]</code>
        &rarr;
        (formatter changes)
        <a href="#formatters">See below</a> or read
        <a href="index.html#scrolling">the user guide</a>
    </li>
    <li>
        <code>record.<em>getValue(fieldName)</em></code> &rarr;
        <code>record.<strong>get(fieldName)</strong></code>
    </li>
</ol>

<h2 id="instantiation">Instantiation and Instance Configuration Changes</h2>

<p>
    As of 3.5.0, `Y.DataTable` is no longer just a namespace, but is now the
    preferred constructor for DataTable instances.
</p>

```
var table = new Y.DataTable({
    // Column configuration looks much the same except the attribute name
    columns: [
        { key: 'name', label: 'Name', sortable: true, width: '200px' },
        {
            key: 'birthdate',
            label: 'Age',
            sortable: true,
            formatter: function (o) {
                var now = new Date(),
                    years = now.getYear() - o.value.getYear();

                now.setYear(o.value.getYear());

                return years - (o.value < now);
            }
        }
    ],
    // Passing in row data looks much the same except the attribute name
    data: [
        { name: 'Tom Brokaw',     birthdate: new Date(1940, 1, 6) },
        { name: 'Peter Jennings', birthdate: new Date(1938, 6, 29) },
        { name: 'Katie Couric',   birthdate: new Date(1957, 1, 7) },
        { name: 'Brian Williams', birthdate: new Date(1958, 4, 5) },
        { name: 'Matt Lauer',     birthdate: new Date(1957, 11, 30) }
    ]
}).render('#over-there');
```

<p>
    The `Y.DataTable.Base` class still exists, but is useful primarily as a
    superclass for extension.  The attributes of `Y.DataTable.Base` are the
    same as those of `Y.DataTable`, less any attributes added by class
    extensions (<a href="#features">see below</a>).
</p>

<p>
    Configuration attributes that have changed from 3.4.1 are:
</p>

<table>
<thead>
    <tr>
        <th>Attribute</th>
        <th>Change</th>
    </tr>
</thead>
<tbody>
    <tr>
        <td>`columnset`</td>
        <td>
            <strong>Deprecated</strong>.  Use `columns`.  `columnset` will
            behave as an alias for `columns` for a short time, but will be
            removed in future versions. <a href="#columns">See below</a>.
        </td>
    </tr>
    <tr>
        <td>`recordset`</td>
        <td>
            <strong>Deprecated</strong>.  Use `data`.  `recordset` will
            behave as an alias for `data` for a short time, but will be
            removed in future versions. <a href="#data">See below</a>.
        </td>
    </tr>
    <tr>
        <td>`tdValueTemplate`</td>
        <td>
            <strong>Removed</strong>. Use column `formatter`, `cellTemplate`,
            or override the `Y.DataTable.BodyView` instance's `CELL_TEMPLATE`.
        </td>
    </tr>
    <tr>
        <td>`thValueTemplate`</td>
        <td>
            <strong>Removed</strong>. Use column `label`, `headerTemplate`,
            or override the `Y.DataTable.HeaderView` instance's `CELL_TEMPLATE`.
        </td>
    </tr>
    <tr>
        <td>`trTemplate`</td>
        <td>
            <strong>Removed</strong>. Use column `nodeFormatter` or override
            the `Y.DataTable.BodyView` instance's `ROW_TEMPLATE`.
        </td>
    </tr>
</tbody>
</table>

<h2 id="formatters">Table and Cell Formatting Changes</h2>

<p>
    The following changes apply to table and column cell formatting:
</p>

<ul>
    <li>
        If cell values include HTML, add `allowHTML: true` to the column
        configuration.  HTML is escaped by default for security.
    </li>
    <li>
        `o.classnames` in the formatter parameter is now `o.className`.
    </li>
    <li>
        `o.column` in the formatter parameter is now <a href="#columns">the
        plain JavaScript object</a> containing the column configurations rather
        than a `Y.Column` instance.
    </li>
    <li>
        `o.record` in the formatter parameter is now <a href="#data">a Model
        instance</a> instead of a `Y.Record` instance.
    </li>
    <li>
        `this.createCell(o)`, `o.td`, `o.tr`, and `o.tbody` no longer exist on
        the parameter passed to `formatter` functions.  Use
        <a href="index.html#nodeformatter">`nodeFormatter`</a>s.
    </li>
    <li>
        `o.headers` is now at `o.column._headers`, but is read-only for
        `formatter` functions.  If you need to change the cell's headers
        attribute, add a {placeholder} for them to a custom `cellTemplate` for
        the column, or use a `nodeFormatter`.
    </li>
    <li>
        The table's `tdValueTemplate`, `thValueTemplate`, and `trTemplate` no
        longer exist, nor do the DataTable instance properties `tdTemplate` and
        `thTemplate`.  Use `formatter` strings or functions to customize the
        content of data cells in a column and `label` strings to customize the
        content of header cells.  To modify the `<td>` or `<th>` entirely, set
        the column configuration `cellTemplate` or `headerTemplate`.
    </li>
</ul>

<div class="yui3-g">
    <div class="yui3-u before">
        <h4 class="no-toc">3.4.1</h4>

        ```
        var table = new Y.DataTable.Base({
            columnset: [
                { key: "id",
                  emptyCellValue: "<em>new</em>" },
                { key: "name" },
                { key: "price", formatter: "${value}" },
                { key: "price",
                  formatter: function (o) {
                    if (o.value > 4) {
                        o.classnames += "spendy";
                    }
                    return '$' + o.value.toFixed(2);
                  }
                },
                { key: "price",
                  formatter: function (o) {
                    var cell = this.createCell(o);

                    if (o.value > 4) {
                        cell.addClass('spendy');
                    }

                    cell.setHTML('$' + o.value);
                  }
                }
            ],
            data: [
                { id: 1, name: "Bread", price: 3.45 },
                { id: 2, name: "Milk",  price: 4.99 },
                { id: 3, name: "Eggs",  price: 2.75 }
            ]
        }).render("#over-there");
        ```
    </div>
    <div class="yui3-u after">
        <h4 class="no-toc">3.5.0</h4>

        ```
        var table = new Y.DataTable({
            columns: [
                { key: "id",
                  emptyCellValue: "<em>new</em>",
                  allowHTML: true },
                { key: "name" },
                { key: "price", formatter: "${value}" },
                { key: "price",
                  formatter: function (o) {
                    if (o.value > 4) {
                        o.className += "spendy";
                    }
                    return '$' + o.value.toFixed(2);
                  }
                },
                { key: "price",
                  nodeFormatter: function (o) {
                    if (o.value > 4) {
                        o.cell.addClass('spendy');
                    }

                    o.cell.setHTML('$' + o.value);

                    return false;
                  }
                }
            ],
            data: [
                { id: 1, name: "Bread", price: 3.45 },
                { id: 2, name: "Milk",  price: 4.99 },
                { id: 3, name: "Eggs",  price: 2.75 }
            ]
        }).render("#over-there");
        ```
    </div>
</div>

<p>
    Read the <a href="index.html#formatters">Formatting Cell Data</a> section in
    the DataTable user guide for more details.
</p>

<h2 id="columns">Column Configuration Changes</h2>

<p>
    As of 3.5.0, the `Y.Columnset` and `Y.Column` classes have been deprecated.
    The DataTable configuration attribute `columnset` has been deprecated in
    favor of the `columns` attribute.  The `columnset` attribute has been
    retained for <em>partial</em> backward compatibility.  Columns are now
    stored as an array of simple JavaScript objects rather than class instances.
</p>

```
var table = new Y.DataTable({
    columnset: [ 'name', 'age' ],
    ...
});

// columnset passes through to columns
var columns = table.get('columns'); // => Array, not Columnset instance

table.set('columnset', [ ... (new column configurations) ... ]);

// backward compatibility stops here
var columnset = table.get('columnset'); // => Array, not Columnset instance
```

<p>
    Strings passed into the column configuration will become objects with those
    strings as the value of the `key` property.
</p>

<p>
    See the <a href="index.html#columns">Column configuration</a> section in
    the user guide for more details.
</p>

<h2 id="data">Row Data Configuration Changes</h2>

<p>
    As of 3.5.0, DataTable uses `Y.Model` and `Y.ModelList` to store row data.
    `Y.Recordset` and `Y.Record` haven't been deprecated, but may be in the
    future.  The `recordset` attribute has been retained for <em>partial</em>
    backward compatibility.  The `data` ModelList can be assigned to, but
    retrieving the value of the attribute will return the ModelList, <em>not
    a `Y.Recordset` instance</em>.
</p>

```
var table = new Y.DataTable({
    columnset: [ ... ],
    recordset: [
        { name: 'Tom Brokaw',     birthdate: new Date(1940, 1, 6) },
        { name: 'Peter Jennings', birthdate: new Date(1938, 6, 29) },
        { name: 'Katie Couric',   birthdate: new Date(1957, 1, 7) },
        ...
    ]
});

// recordset passes through to data.
var data = table.get('data'); // => ModelList instance

table.set('recordset', [ ... (new data records) ... ]);

// backward compatibility stops here
var recordset = table.get('recordset'); // => ModelList, not Recordset
```

<p>
    `Y.Record` stores all values in a single attribute named `data`, where `Y.Model` uses individual attributes for each value.
</p>

<div class="yui3-g">
    <div class="yui3-u before">
        <h4 class="no-toc">3.4.1</h4>

        ```
        // Y.Record
        var record = oldTable.get('recordset').item(0);

        record.getValue('birthdate'); // => Date(1940, 1, 6)
        record.get('data').birthdate; // => same
        ```
    </div>
    <div class="yui3-u after">
        <h4 class="no-toc">3.5.0</h4>
        ```
        // Y.Model
        var model = newTable.getRecord(0);

        model.get('birthdate'); // => Date(1940, 1, 6)
        ```
    </div>
</div>

<p>
    <strong>This change breaks column/record keys that contain periods</strong>.
    Attribute treats periods as subproperty indicators, so periods are no
    longer allowed;  use an alternate character.  In the case of remote data
    that is parsed by `Y.Plugin.DataSourceJSONSchema`, use the `locator`
    configuration for fields to extract subproperty values.  A benefit to doing
    this is that you may not need to specify a column `label`.
</p>

<div class="yui3-g">
    <div class="yui3-u before">
        <h4 class="no-toc">3.4.1</h4>

        ```
        var table = new Y.DataTable.Base({
            columnset: [
                { key: "id" },
                { key: "Product.Name",  label: "Product" },
                { key: "Product.Price", label: "Price" }
            ],
            caption: "Price List"
        }).plug(Y.Plugin.DataTableDataSource, {
            datasource: new Y.DataSource.IO({
                source: "/service/price-list"
            }).plug(Y.Plugin.DataSourceJSONSchema, {
                schema: {
                    resultListLocator: "items",
                    resultFields: [
                        { key: "id" },
                        { key: "Product.Name" },
                        { key: "Product.Price" }
                    ]
                }
            })
        });

        table.datasource.load(...);
        ```
    </div>
    <div class="yui3-u after">
        <h4 class="no-toc">3.5.0</h4>

        ```
        var table = new Y.DataTable({
            columns: [ "id", "Product", "Price" ],
            caption: "Price List"
        }).plug(Y.Plugin.DataTableDataSource, {
            datasource: new Y.DataSource.IO({
                source: "/service/price-list"
            }).plug(Y.Plugin.DataSourceJSONSchema, {
                schema: {
                    resultListLocator: "items",
                    resultFields: [
                        { key: "id" },
                        { key: "Product",
                          locator: "Product.Name" },
                        { key: "Price",
                          locator: "Product.Price" }
                    ]
                }
            })
        });

        table.datasource.load(...);
        ```
    </div>
</div>

<p>
    If you are using any Recordset plugins, your code will need to be modified.
    Some loss of functionality may result.
</p>

<dl>
    <dt>`Y.Plugin.RecordsetSort`</dt>
    <dd>
        This plugin was formerly applied by the `Y.Plugin.DataTableSort` plugin
        to the DataTable's Recordset instance.  Sorting is now enabled
        <a href="#features">through a class extension</a>.
    </dd>

    <dt>`Y.Plugin.RecordsetFilter`</dt>
    <dd>
        The default ModelList implementation only supports a `filter(function)`
        method.  If you were relying on this plugin's `grep` or `reject`
        methods or the `filter(key, value)` functionality, you will need to
        replace that functionality through custom code.
    </dd>

    <dt>`Y.Plugin.RecordsetIndexer`</dt>
    <dd>
        The default ModelList implementation does not support multiple custom
        indexes, though it does maintain an index for `id` (or another,
        assigned primary key attribute) and `clientId`.  See
        <a href="../model/index.html">the Model user guide</a> for more
        information on customizing the primary index.  If multiple custom
        indexes are required, DataTable supports the use of
        <a href="#recordtype">custom Model subclasses</a> to store the record
        data.
    </dd>
</ul>

<p>
    See the <a href="#data">Data Configuration section</a> of the DataTable
    user guide for more information.
</p>

<h2 id="features">Feature Configuration Changes</h2>

<p>
    The two optional features available for DataTable in 3.4.1 were sorting and
    scrolling.  Both features exist in 3.5.0, but are implemented as class
    extensions for `Y.DataTable`.  Simply including the `datatable-sort` or
    `datatable-scroll` module in your `use(...)` will enable the feature for
    all new DataTables.
</p>

```
YUI().use('datatable-sort', 'datatable-scroll', function (Y) {

    // Create a DataTable that is sortable by the "name" column, and is
    // configured to scroll vertically within 300px.  Because scrollable is
    // set to "y", not "x" or "xy", it will not attempt to scroll horizontally.
    // Instead the table width will be set to 100%.
    var table = new Y.DataTable({
        columns   : [ { key: 'name', sortable: true }, ... ],
        data      : [ ... ],
        scrollable: "y",
        height    : "300px",
        width     : "100%"
    });

    // No plugins necessary
    table.render('#over-there');
});
```

<h3 id="sorting">Column Sorting Changes</h3>

<p>
    Configuring sortable columns may be done as it was in 3.4.1, by setting the
    column configuration property `sortable: true`, but may also be done by
    setting the DataTable's `sortable` configuration to `true` or an array of
    column names.
</p>

<div class="yui3-g">
    <div class="yui3-u before">
        <h4 class="no-toc">3.4.1</h4>

        ```
        // Assumes use('datatable-sort') or use('datatable')
        var table = new Y.DataTable.Base({
            columnset: [
                { key: "id" },
                { key: "name", sortable: true },
                { key: "price", sortable: true }
            ],
            recordset: [
                { id: 1, name: "Bread", price: 3.45 },
                { id: 2, name: "Milk",  price: 4.99 },
                { id: 3, name: "Eggs",  price: 2.75 },
                ...
            ],
            caption: "Price List"
        });

        table.plug(Y.Plugin.DataTableSort);

        table.render('#sort-demo');

        // Sorting API is on the Recordset's plugin
        table.get("recordset").sort.sort("name");
        ```
    </div>
    <div class="yui3-u after">
        <h4 class="no-toc">3.5.0</h4>

        ```
        // Assumes use('datatable-sort') or use('datatable')
        var table = new Y.DataTable({
            columns: [ "id", "name", "price" ],
            data: [
                { id: 1, name: "Bread", price: 3.45 },
                { id: 2, name: "Milk",  price: 4.99 },
                { id: 3, name: "Eggs",  price: 2.75 },
                ...
            ],
            sortable: [ "name", "price" ]
        });

        table.render('#sort-demo');

        // Sort method is on the instance
        table.sort("name");

        //-------------------------------------------------
        // Alternate methods
        //-------------------------------------------------

        var table = new Y.DataTable({
            columns: [ "id", "name", "price" ],
            data: [ ... ],
            sortable: true // makes all columns sortable
        });

        // OR the old way works, too
        var table = new Y.DataTable({
            columns: [
                { key: "id" },
                { key: "name", sortable: true },
                { key: "price", sortable: true }
            ],
            data: [ ... ]
        });
        ```
    </div>
</div>

<p>
    Since there is no plugin, the `sort` method is now on the DataTable instance
    itself, as are the related attributes.  In particular, the `lastSortedBy`
    attribute from the plugin implementation has been replaced by the `sortBy`
    attribute added by the class extension.
</p>

<p>
    As of 3.5.0, DataTables configured with `sortBy` will have their rows
    sorted automatically upon inserting into the table.  You do not need to
    presort data for the initial render.
</p>

<p>
    <strong>The `trigger` attribute of the sorting plugin was not retained in
    the 3.5.0 class extension</strong>.  If you require an alternate triggering
    event, detach and replace the table's `_sortHandle` property after
    `render()`.
</p>

```
var table = new Y.DataTable({ ... }).render("#over-there");

table._sortHandle.detach();
table._sortHandle = table.delegate(["dblclick", "keydown"],
    table._onUITriggerSort, ".yui3-datatable-sortable-column", table);
```

<p>
    See the <a href="index.html#sorting">Column Sorting section</a> of the
    user guide for details about the APIs and attributes.
</p>

<h3 id="scrolling">Scrollable Table Changes</h3>

<p>
    Like sorting, the scrolling functionality has been moved to a class
    extension, making it unnecessary to plug the DataTable instance with the
    (now deprecated) `Y.Plugin.DataTableScroll` plugin.
</p>

<p>
    <strong>`datatable-scroll` is no longer included in the `datatable`
    rollup</strong>, and must be explicitly included in your `use()` statement.
</p>

<p>
    To enable scrolling in 3.5.0, set the table's `scrollable` attribute to "x",
    "y", or "xy".  The configured `height` and `width` for the DataTable are
    used to bound the overall widget dimesions.  Scrolling will only be applied
    on the axis or axes specified in `scrollable`.  However, if `scrollable` is
    set to "y", but the `height` isn't set, it will not be made scrollable.
    Likewise for "x" and `width`.
</p>

<div class="yui3-g">
    <div class="yui3-u before">
        <h4 class="no-toc">3.4.1</h4>

        ```
        // Assumes use("datatable-scroll") or use("datatable")
        var table = new Y.DataTable.Base({
            columnset: ["id", "name", "price"],
            recordset: [
                { id: 1, name: "Bread", price: 3.45 },
                { id: 2, name: "Milk",  price: 4.99 },
                { id: 3, name: "Eggs",  price: 2.75 },
                ...
            ]
        });

        table.plug(Y.Plugin.DataTableScroll, {
            height: "175px"
        });

        table.render("#over-there");
        ```
    </div>
    <div class="yui3-u after">
        <h4 class="no-toc">3.5.0</h4>

        ```
        // Assumes use("datatable-scroll")
        var table = new Y.DataTable({
            columns: ["id", "name", "price"],
            data: [
                { id: 1, name: "Bread", price: 3.45 },
                { id: 2, name: "Milk",  price: 4.99 },
                { id: 3, name: "Eggs",  price: 2.75 },
                ...
            ],
            scrollable: "y",
            height: "175px"
        }).render("#over-there");
        ```
    </div>
</div>

<h2 id="markup">Markup and CSS Changes</h2>

<p>
    DataTable in 3.5.0 applies more CSS classes to Nodes, stamps fewer nodes
    with guid ids, and does not render header and cell liner `<div>`s.
</p>

<p>
    Below are examples of the same table rendered in 3.4.1 and 3.5.0.  The 3.5.0
    table has comments indicating markup added by feature modules.
</p>

<h4 class="no-toc">3.4.1</h4>
```
<div id="(guid)" class="yui3-widget yui3-datatable">
  <div id="(guid)" class="yui3-datatable-content">
    <table>

      <caption>
        Example table with simple columns
      </caption>

      <colgroup>
        <col>
        <col>
        <col>
      </colgroup>

    <thead class="yui3-datatable-columns">
      <tr id="" class="yui3-datatable-first yui3-datatable-last">
        <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-id" abbr="">
          <div class="yui3-datatable-liner">
            id
          </div>
        </th>
        <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-name" abbr="">
          <div class="yui3-datatable-liner">
            name
          </div>
        </th>
        <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-price" abbr="">
          <div class="yui3-datatable-liner">
            price
          </div>
        </th>
      </tr>
    </thead>

    <tbody class="yui3-datatable-msg">
    </tbody>

    <tbody class="yui3-datatable-data" id="(guid)">
      <tr id="(guid)" class="yui3-datatable-even">
        <td headers="(guid)" class="yui3-column-id">
          <div class="yui3-datatable-liner">
            1
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-name">
          <div class="yui3-datatable-liner">
            Bread
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-price">
          <div class="yui3-datatable-liner">
            3.45
          </div>
        </td>
      </tr>
      <tr id="(guid)" class="yui3-datatable-odd">
        <td headers="(guid)" class="yui3-column-id">
          <div class="yui3-datatable-liner">
            2
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-name">
          <div class="yui3-datatable-liner">
            Milk
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-price">
          <div class="yui3-datatable-liner">
            4.99
          </div>
        </td>
      </tr>
      <tr id="(guid)" class="yui3-datatable-even">
        <td headers="(guid)" class="yui3-column-id">
          <div class="yui3-datatable-liner">
            3
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-name">
            <div class="yui3-datatable-liner">
              Eggs
            </div>
          </td>
          <td headers="(guid)" class="yui3-column-price">
            <div class="yui3-datatable-liner">
              2.75
            </div>
          </td>
        </tr>
      </tbody>

    </table>
  </div>
</div>
```

<h4 class="no-toc">3.5.0</h4>
```
<div id="(guid)" class="yui3-widget yui3-datatable">
  <div id="(guid)" class="yui3-datatable-content">
    <table cellspacing="0" class="yui3-datatable-table" id="(guid)">

      <caption class="yui3-datatable-caption">
        Price List
      </caption>

      <!-- colgroup only renders if datatable-column-widths is use()d.
           Note, datatable-column-widths is included in the datatable rollup -->
      <colgroup id="(guid)">
        <col>
        <col>
        <col>
      </colgroup>

      <thead class="yui3-datatable-columns" id="(guid)">
        <tr>
          <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-first-header yui3-datatable-col-id" scope="col" data-yui3-col-id="id">
            id
          </th>
          <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-col-name" scope="col" data-yui3-col-id="name">
            name
          </th>
          <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-col-price" scope="col" data-yui3-col-id="price">
            price
          </th>
        </tr>
      </thead>

      <!-- The message tbody only renders if datatable-message is use()d.
           Note, datatable-message is included in the datatable rollup -->
      <tbody class="yui3-datatable-message" id="(guid)">
        <tr>
          <td class="yui3-datatable-message-content" colspan="3">
            No data to display
          </td>
        </tr>
      </tbody>

      <tbody class="yui3-datatable-data">
        <tr id="(guid)" data-yui3-record="record_1" class="yui3-datatable-even">
          <td class="yui3-datatable-col-id  yui3-datatable-cell">
            1
          </td>
          <td class="yui3-datatable-col-name  yui3-datatable-cell">
            Bread
          </td>
          <td class="yui3-datatable-col-price  yui3-datatable-cell">
            3.45
          </td>
        </tr>
        <tr id="(guid)" data-yui3-record="record_2" class="yui3-datatable-odd">
          <td class="yui3-datatable-col-id  yui3-datatable-cell">
            2</td>
          <td class="yui3-datatable-col-name  yui3-datatable-cell">
            Milk
          </td>
          <td class="yui3-datatable-col-price  yui3-datatable-cell">
            4.99
          </td>
        </tr>
        <tr id="(guid)" data-yui3-record="record_3" class="yui3-datatable-even">
          <td class="yui3-datatable-col-id  yui3-datatable-cell">
            3
          </td>
          <td class="yui3-datatable-col-name  yui3-datatable-cell">
            Eggs
          </td>
          <td class="yui3-datatable-col-price  yui3-datatable-cell">
            2.75
          </td>
        </tr>
      </tbody>

    </table>
  </div>
</div>
```

<h2 id="help-me">What Did I Miss?</h2>

<p>
    Obviously, there were a lot of changes to DataTable from 3.4.1 to 3.5.0.
    It's entirely likely that I have missed something here.  If you experience
    trouble with your upgrade and find this migration guide is missing
    something important, please <a href="/projects/yui3/newticket">file a
    ticket</a> and I'll update it as soon as possible.
</p>

<p>
    Additional resources to help with the upgrade include the
    <a href="/forum">forums</a>, and the #yui IRC channel on freenode.net.
</p>
